using Clancy.Ui.Factories;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Controls;
using System.Windows.Controls.Ribbon;

namespace Clancy.Ui.ViewModels
{
    public abstract class RibbonElementConsumingViewModelBase : ViewModelBase
    {
        private readonly List<RibbonTab> m_RibbonContent = new List<RibbonTab>();
        private readonly Dictionary<RibbonGroup, List<Control>> m_RibbonElementsForGroup = new Dictionary<RibbonGroup, List<Control>>();
        private readonly Dictionary<RibbonTab, List<RibbonGroup>> m_RibbonGroupsForTabs = new Dictionary<RibbonTab, List<RibbonGroup>>();

        public IEnumerable<RibbonTab> RibbonContent
        {
            get { return m_RibbonContent; }
        }

        protected void FillRibbon(ObservableCollection<RibbonElement> ribbonElements)
        {
            foreach (RibbonElement element in ribbonElements)
            {
                RibbonTab tabToInsert = GetTabToInsert(element);
                RibbonGroup groupToInsert = GetGroupToInsert(tabToInsert, element);
                InsertElement(groupToInsert, element);
            }
        }

        private RibbonGroup GetGroupToInsert(RibbonTab tabToInsert, RibbonElement element)
        {
            RibbonGroup groupToInsert = tabToInsert.ItemsSource.Cast<RibbonGroup>().FirstOrDefault(group => @group.Header.Equals(element.Group));
            if (groupToInsert == null)
            {
                groupToInsert = new RibbonGroup { Header = element.Group };
                m_RibbonElementsForGroup[groupToInsert] = new List<Control>();
                groupToInsert.ItemsSource = m_RibbonElementsForGroup[groupToInsert];
                m_RibbonGroupsForTabs[tabToInsert].Add(groupToInsert);
            }
            return groupToInsert;
        }

        private RibbonTab GetTabToInsert(RibbonElement element)
        {
            RibbonTab tabToInsert = m_RibbonContent.FirstOrDefault(tab => tab.Header.Equals(element.Tab));
            if (tabToInsert == null)
            {
                tabToInsert = new RibbonTab { Header = element.Tab };
                m_RibbonGroupsForTabs[tabToInsert] = new List<RibbonGroup>();
                tabToInsert.ItemsSource = m_RibbonGroupsForTabs[tabToInsert];
                m_RibbonContent.Add(tabToInsert);
            }
            return tabToInsert;
        }

        private void InsertElement(RibbonGroup groupToInsert, RibbonElement element)
        {
            Control newElement = RibbonElementFactory.CreateElement(groupToInsert, element);
            if (newElement != null)
            {
                m_RibbonElementsForGroup[groupToInsert].Add(newElement);
            }
        }
    }
}